package com.wujie.mall.domain.pricing;

import lombok.Data;
import lombok.Builder;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
import java.util.List;
import java.util.ArrayList;

/**
 * 定价结果
 * 
 * 封装定价策略执行后的结果信息，包括：
 * - 最终价格
 * - 折扣信息
 * - 优惠明细
 * - 策略应用记录
 * 
 * @author wujie
 * @since 2024-08-26
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PricingResult {

    /**
     * 原价
     */
    private BigDecimal originalPrice;

    /**
     * 最终价格
     */
    private BigDecimal finalPrice;

    /**
     * 折扣金额
     */
    private BigDecimal discountAmount;

    /**
     * 折扣率（0.1 表示 10% 折扣）
     */
    private BigDecimal discountRate;

    /**
     * 应用的策略名称
     */
    private String appliedStrategy;

    /**
     * 策略应用说明
     */
    private String strategyDescription;

    /**
     * 是否成功应用策略
     */
    private Boolean success;

    /**
     * 错误信息（如果失败）
     */
    private String errorMessage;

    /**
     * 优惠明细列表
     */
    @Builder.Default
    private List<DiscountDetail> discountDetails = new ArrayList<>();

    /**
     * 扩展信息
     */
    private java.util.Map<String, Object> extras;

    /**
     * 优惠明细内部类
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    public static class DiscountDetail {
        /**
         * 优惠类型
         */
        private String discountType;

        /**
         * 优惠名称
         */
        private String discountName;

        /**
         * 优惠金额
         */
        private BigDecimal discountAmount;

        /**
         * 优惠说明
         */
        private String description;
    }

    /**
     * 创建成功的定价结果
     * @param originalPrice 原价
     * @param finalPrice 最终价格
     * @param strategyName 策略名称
     * @return 定价结果
     */
    public static PricingResult success(BigDecimal originalPrice, BigDecimal finalPrice, String strategyName) {
        BigDecimal discountAmount = originalPrice.subtract(finalPrice);
        BigDecimal discountRate = discountAmount.divide(originalPrice, 4, java.math.RoundingMode.HALF_UP);
        
        return PricingResult.builder()
                .originalPrice(originalPrice)
                .finalPrice(finalPrice)
                .discountAmount(discountAmount)
                .discountRate(discountRate)
                .appliedStrategy(strategyName)
                .success(true)
                .build();
    }

    /**
     * 创建失败的定价结果
     * @param originalPrice 原价
     * @param strategyName 策略名称
     * @param errorMessage 错误信息
     * @return 定价结果
     */
    public static PricingResult failure(BigDecimal originalPrice, String strategyName, String errorMessage) {
        return PricingResult.builder()
                .originalPrice(originalPrice)
                .finalPrice(originalPrice) // 失败时返回原价
                .discountAmount(BigDecimal.ZERO)
                .discountRate(BigDecimal.ZERO)
                .appliedStrategy(strategyName)
                .success(false)
                .errorMessage(errorMessage)
                .build();
    }

    /**
     * 添加优惠明细
     * @param discountType 优惠类型
     * @param discountName 优惠名称
     * @param discountAmount 优惠金额
     * @param description 说明
     */
    public void addDiscountDetail(String discountType, String discountName, BigDecimal discountAmount, String description) {
        if (discountDetails == null) {
            discountDetails = new ArrayList<>();
        }
        discountDetails.add(DiscountDetail.builder()
                .discountType(discountType)
                .discountName(discountName)
                .discountAmount(discountAmount)
                .description(description)
                .build());
    }

    /**
     * 获取总优惠金额
     * @return 总优惠金额
     */
    public BigDecimal getTotalDiscountAmount() {
        if (discountDetails == null || discountDetails.isEmpty()) {
            return discountAmount != null ? discountAmount : BigDecimal.ZERO;
        }
        return discountDetails.stream()
                .map(DiscountDetail::getDiscountAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 检查是否有优惠
     * @return 是否有优惠
     */
    public boolean hasDiscount() {
        return discountAmount != null && discountAmount.compareTo(BigDecimal.ZERO) > 0;
    }

    /**
     * 获取折扣率百分比（如：0.1 -> "10%"）
     * @return 折扣率百分比字符串
     */
    public String getDiscountRatePercentage() {
        if (discountRate == null) {
            return "0%";
        }
        return discountRate.multiply(BigDecimal.valueOf(100))
                .setScale(1, java.math.RoundingMode.HALF_UP) + "%";
    }

    /**
     * 获取结果摘要
     * @return 结果摘要
     */
    public String getSummary() {
        if (!success) {
            return String.format("定价失败：%s，原价：%s", errorMessage, originalPrice);
        }
        
        if (hasDiscount()) {
            return String.format("策略：%s，原价：%s，优惠：%s，实付：%s（%s折扣）", 
                    appliedStrategy, originalPrice, discountAmount, finalPrice, getDiscountRatePercentage());
        } else {
            return String.format("策略：%s，价格：%s（无优惠）", appliedStrategy, finalPrice);
        }
    }
}